package model.characters;

import java.awt.Rectangle;
import java.util.List;

import model.ComponentTypeEnum;
import model.GameContext;
import model.LayerEnum;
import model.characters.weapons.Weapon;
import model.components.ScreenComponentUtil;

public class Character implements CharacterInterface{

	private Integer life;
	private ComponentTypeEnum type;
	private Rectangle region;
	private Rectangle hand;
	private CharacterStateEnum state;
	private List<Weapon> weapons;
	private Weapon currentWeapon;
	private LayerEnum layer;

	boolean walking;
	boolean walkingR;
	boolean walkingL;
	boolean running;
	boolean shooting;
	boolean jumping;
	boolean falling;
	boolean lowered;
	boolean dead;

	int direction = GameContext.RIGHT_DIRECTION; //default

	int rightDirection;
	int leftDirection;

	int jumpSize = 15;
	int jumpCount;

	Integer stateCode = 1;
	private CharacterState chacterState;

	public Character(ComponentTypeEnum type) {
		life = 300;
		region = new Rectangle(50,1,GameContext.STANDING_WIDTH,GameContext.STANDING_HEIGHT);
		hand = new Rectangle(20, 20);
		hand.x = region.x+region.width;
		layer = LayerEnum.LAYER_1;
		this.type = type;
		this.state = CharacterStateEnum.IDLE_RIGHT;
		chacterState = new CharacterState();

	}

	public Character(Integer life, Rectangle region, ComponentTypeEnum type) {
		this.life = life;
		this.region = region;
		hand = new Rectangle(20, 20);
		hand.x = region.x+region.width;
		layer = LayerEnum.LAYER_1;
		this.type = type;
		this.state = CharacterStateEnum.IDLE_RIGHT;
		chacterState = new CharacterState();
	}

	@Override
	public void update() {

		if(falling && !jumping)
			fall(direction);

		if(!isDead()){
			if(jumping)
				jump();
			if(shooting)
				shoot();

			state = chacterState.stateMap.get(stateCode);

			if(state == null){
				state = CharacterStateEnum.IDLE_RIGHT;
			}

		}else{
			state = chacterState.stateMap.get(CharacterState.DYING * getDirection());
		}




	}

	private void shoot() {

		stateCode += CharacterState.SHOTTING * getDirection();
		getCurrentWeapon().use(getDirection());

		if(!getCurrentWeapon().isUsing()){
			shooting = false;
		}
	}

	@Override
	public void walk(Integer direction) {
		stateCode = CharacterState.WALKING * getDirection();
		//Implementado pelo PlayerCameraDecorator
		//getRegion().x += direction;

	}

	@Override
	public void run(Integer direction) {
		stateCode = CharacterState.RUNNING * getDirection();
		//Implementado pelo PlayerCameraDecorator
		//getRegion().x += direction*3;
	}

	@Override
	public void jump() {
		stateCode = CharacterState.JUMPING * getDirection();
		region.y -= 10;
		if(jumpCount++ >= jumpSize){
			jumping = false;
			jumpCount=0;
		}
	}

	@Override
	public void turnDown() {
		if(!lowered){
			stateCode = CharacterState.LOWERED * direction;

			getRegion().y += GameContext.LOWERED_Y;

		}
	}

	@Override
	public void turnUp() {
		if(lowered){
			state = CharacterStateEnum.IDLE_RIGHT;
			getRegion().y -= GameContext.LOWERED_Y;

		}
	}

	@Override
	public void fall(Integer direction) {
		stateCode = CharacterState.FALLING * getDirection();
		region.y += 8;
	}

	@Override
	public Integer getLife() {
		return life;
	}

	@Override
	public Rectangle getRegion() {
		region.width = state.getRegion().width;
		region.height = state.getRegion().height;
		return region;
	}

	@Override
	public CharacterStateEnum getState() {
		return state;
	}

	@Override
	public void setState(CharacterStateEnum state) {
		this.state = state;
	}

	@Override
	public void die(){
		region.height = region.height/2;
		region.y += region.height;

		dead = true;

	}

	@Override
	public void setDirection(Integer direction) {
		if(direction != GameContext.NULL_DIRECTION)
			this.direction = direction;
	}

	@Override
	public List<Weapon> getWeapons() {
		return weapons;
	}

	@Override
	public Weapon getCurrentWeapon() {
		return currentWeapon;
	}

	@Override
	public void setWalkingR(boolean walkingR) {
		this.walkingR = walkingR;
	}

	@Override
	public void setWalkingL(boolean walkingL) {
		this.walkingL = walkingL;
	}

	@Override
	public void setRunning(boolean running) {
		this.running = running;
	}

	@Override
	public void setShooting(boolean shooting) {
		this.shooting = shooting;
	}

	@Override
	public boolean isRunning() {
		return running;
	}

	@Override
	public boolean isJumping() {
		return jumping;
	}

	@Override
	public boolean isShooting() {
		return shooting;
	}

	@Override
	public boolean isFalling() {
		return falling;
	}

	@Override
	public void setFalling(boolean falling) {
		this.falling = falling;
	}

	@Override
	public Integer getDirection() {
		if(direction == GameContext.NULL_DIRECTION)
			return GameContext.RIGHT_DIRECTION;
		return direction;
	}

	@Override
	public void setJumping(boolean jumping) {
		if(!falling)
			this.jumping = jumping;
	}

	@Override
	public void setRightDirection(int rightDirection) {
		this.rightDirection = rightDirection;
	}

	@Override
	public void setLeftDirection(int leftDirection) {
		this.leftDirection = leftDirection;
	}

	@Override
	public boolean isWalkingR() {
		return walkingR;
	}

	@Override
	public boolean isWalkingL() {
		return walkingL;
	}

	@Override
	public int getRightDirection() {
		return rightDirection;
	}

	@Override
	public Rectangle getHand() {
		return hand;
	}

	@Override
	public void setCurrentWeapon(Weapon currentWeapon) {
		this.currentWeapon = currentWeapon;
	}

	@Override
	public int getLeftDirection() {
		return leftDirection;
	}

	@Override
	public void setLife(Integer life) {
		this.life = life;
		ScreenComponentUtil.update(this);

	}
	@Override
	public boolean isLowered() {
		return lowered;
	}

	@Override
	public void setLowered(boolean lowered) {
		this.lowered = lowered;
	}

	@Override
	public LayerEnum getLayer() {
		return layer;
	}

	@Override
	public ComponentTypeEnum getType() {
		return type;
	}

	@Override
	public boolean isDead() {
		return dead;
	}

	@Override
	public int getStateCode() {
		return stateCode;
	}

	@Override
	public void setStateCode(Integer stateCode) {
		this.stateCode = stateCode;
	}

	@Override
	public boolean isWalking() {
		return walking;
	}

	@Override
	public void setWalking(boolean walking) {
		this.walking = walking;
	}
}
